#include "i2c_core.h"
#include "i2c_bitops.h"
#include "i2c_hw.h"
#include "Dwt_Delay_Us.h"
/********************eg: stm32f1 simulate i2c start*******************/
 
//i2c1 device
struct i2c_dev_device i2c1_dev;
struct ops_i2c_dev ops_i2c1_dev; 


//#define GPIO_MODE             0x00000003U

#define SET_PIN_DIRECT(GPIOx,Pin,Mode) 			do{uint32_t temp = 0x00U;  temp = GPIOx->MODER;	\
																							temp &= ~(GPIO_MODER_MODER0 << (Pin * 2U));	\
																							temp |= ((Mode & GPIO_MODE) << (Pin * 2U));	\
																							GPIOx->MODER = temp;}while(0)

//i2c1 diver
static void gpio_set_sda(int8_t state)
{
	SET_PIN_DIRECT(I2C1_SDA_PORT, I2C1_SDA_PIN_IDX, GPIO_MODE_OUTPUT_PP);
	if (state)
	{
		I2C1_SDA_PORT->BSRR = I2C1_SDA_PIN;
	}
	else
	{
		I2C1_SDA_PORT->BSRR = ((uint32_t)I2C1_SDA_PIN << 16U);
	}
}

static void gpio_set_scl(int8_t state)
{
	SET_PIN_DIRECT(I2C1_SCL_PORT, I2C1_SCL_PIN, GPIO_MODE_OUTPUT_PP);
	
	if (state)
	{	
		I2C1_SCL_PORT->BSRR = I2C1_SCL_PIN;
	}
	else
	{	
		I2C1_SCL_PORT->BSRR = ((uint32_t)I2C1_SCL_PIN << 16U);
	}
}

static int8_t gpio_get_sda(void)
{
	SET_PIN_DIRECT(I2C1_SDA_PORT, I2C1_SDA_PIN_IDX, GPIO_MODE_INPUT);
	return (I2C1_SDA_PORT->IDR & I2C1_SDA_PIN);
}

static int8_t gpio_get_scl()
{
	SET_PIN_DIRECT(I2C1_SCL_PORT, I2C1_SCL_PIN, GPIO_MODE_INPUT);
	return (I2C1_SCL_PORT->IDR & I2C1_SCL_PIN);
}

static inline void gpio_delayus(uint32_t us)
{
		DWT_Delay_us(us);
}

int ops_i2c_bus_xfer(struct i2c_dev_device *i2c_dev,struct i2c_dev_message msgs[],unsigned int num)
{
	return(i2c_bitops_bus_xfer((struct ops_i2c_dev*)(i2c_dev->i2c_phy),msgs,num));
}

uint8_t TestSMIIC(void)
{
	uint8_t tmp = 0;
	gpio_set_sda(0);
	tmp = gpio_get_sda();
	gpio_set_sda(1);
	tmp = gpio_get_sda();
	
	gpio_set_scl(0);
	tmp = gpio_get_scl();
	gpio_set_scl(1);
	tmp = gpio_get_scl();
	
	return tmp;
}

void stm32f4xx_i2c_init(void)
{
	GPIO_InitTypeDef GPIO_InitStruct = {0};										
	__HAL_RCC_GPIOC_CLK_ENABLE();
	
	GPIO_InitStruct.Pin = I2C1_SDA_PIN|I2C1_SCL_PIN;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
	
	I2C1_SDA_PORT->BSRR = I2C1_SDA_PIN;											
	I2C1_SCL_PORT->BSRR = I2C1_SCL_PIN;
		
	//device init
	ops_i2c1_dev.set_sda = gpio_set_sda;
	ops_i2c1_dev.get_sda = gpio_get_sda;
	ops_i2c1_dev.set_scl = gpio_set_scl;
	ops_i2c1_dev.get_scl = gpio_get_scl;
	ops_i2c1_dev.delayus = gpio_delayus;
	
	uint8_t test = TestSMIIC();
			
	i2c1_dev.i2c_phy	 = &ops_i2c1_dev;
	i2c1_dev.xfer		 = ops_i2c_bus_xfer; 
}
/********************eg: stm32f1 simulate i2c end*******************/
